﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iLangl.Model;
using iLangl.BusinessModel.DAL;

namespace iLangl.BusinessModel.Managers
{
	public class ProjectManager
	{
		#region Singelton Pattern
		private ProjectManager()
		{
		}

		private static ProjectManager instance;
		private static object mutex = new object();
		/// <summary>
		/// The instance of the ProjectManager.
		/// </summary>
		public static ProjectManager Instance
		{
			get
			{
				if (instance == null)
				{
					lock (mutex)
					{
						if (instance == null)
						{
							instance = new ProjectManager();
						}
					}
				}
				return instance;
			}
		}
		#endregion

		public void ToLocalLanguagesMapping(Project project, PluginLicense license)
		{
			foreach (ContentEntity content in project.Contents)
			{
				Language language = LanguageManager.Instance.GetLanguage(license.Plugin.ID, content.Language.LanguageId);
				if (language == null)
				{
					MappingException(license, content.Language.LanguageId);
					return;
				}

				content.Language = language;
			}

			foreach (Translation trans in project.Translations)
			{

				Language language = LanguageManager.Instance.GetLanguage(license.Plugin.ID, trans.LanguagePair.SourceLanguage.LanguageId);
				if (language == null)
				{
					MappingException(license, trans.LanguagePair.SourceLanguage.LanguageId);
					return;
				}
				trans.LanguagePair.SourceLanguage = language;
				language = LanguageManager.Instance.GetLanguage(license.Plugin.ID, trans.LanguagePair.TargetLanguage.LanguageId);
				if (language == null)
				{
					MappingException(license, trans.LanguagePair.TargetLanguage.LanguageId);
					return;
				}
				trans.LanguagePair.TargetLanguage = language;
			}
		}

		public void ToPluginLanguagesMapping(Project project, PluginLicense license)
		{
			foreach (ContentEntity content in project.Contents)
			{
				Language language = LanguageManager.Instance.GetPluginLanguage(license.Plugin.ID, content.Language.LanguageId);
				if (language == null)
				{
					MappingException(license, content.Language.LanguageId);
					return;
				}

				content.Language = language;
			}

			foreach (Translation trans in project.Translations)
			{
				Language language = LanguageManager.Instance.GetPluginLanguage(license.Plugin.ID, trans.LanguagePair.SourceLanguage.LanguageId);
				if (language == null)
				{
					MappingException(license, trans.LanguagePair.SourceLanguage.LanguageId);
					return;
				}
				trans.LanguagePair.SourceLanguage = language;
				language = LanguageManager.Instance.GetPluginLanguage(license.Plugin.ID, trans.LanguagePair.TargetLanguage.LanguageId);
				if (language == null)
				{
					MappingException(license, trans.LanguagePair.TargetLanguage.LanguageId);
					return;
				}
				trans.LanguagePair.TargetLanguage = language;
			}
		}

		private void MappingException(PluginLicense license, String languageCode)
		{
			IAlert alert = Facade.Instance.AlertManager.CreateAlert(this);
			Error error = new Error(
				"Mapping Exception",
				String.Format("Missed mapping data for plugin '{0}' with Id='{1}' for Language Code={2}", license.Plugin.Name, license.Plugin.ID, languageCode),
				eSeverity.High);
			alert.AddError(error);
			Facade.Instance.AlertManager.RaiseAlert(alert);

		}

		public void RegisterProject(Project project)
		{
			if (project.Owner != null)
			{
				CompanyManager.Instance.CreateCompany((Company)project.Owner.Company);
				ContactManager.Instance.CreateContact(project.Owner);
			}
			
			if (project.TechnicalContact != null)
			{
				CompanyManager.Instance.CreateCompany((Company)project.TechnicalContact.Company);
				ContactManager.Instance.CreateContact(project.TechnicalContact);
			}

			//Transfer codes to iLangl Format

			DALFacade.Instance.ProjectDAL.CreateProject(project, null);

			foreach (ContentEntity content in project.Contents)
			{
				DALFacade.Instance.ContentDAL.CreateContent(content, null);
			}

			foreach (Translation translation in project.Translations)
			{
				if (translation.Responsible != null)
				{
					CompanyManager.Instance.CreateCompany((Company)translation.Responsible.Company);
					ContactManager.Instance.CreateContact(translation.Responsible);
				}

				DALFacade.Instance.TranslationDAL.CreateTranslation(translation, null);
			}

			//Subscribe to Synchronization

			if (!String.IsNullOrEmpty(project.LicenseKey))
			{
				PluginLicense pl = PluginManager.Instance.GetLicense(project.LicenseKey);

				AddSubscriber(project, pl, false);
				CompanyManager.Instance.AddSubscriber((Company)project.Owner.Company, pl, false);
			}
		}

		public Project GetProject(String projectId)
		{
			Project project = DALFacade.Instance.ProjectDAL.ReadProject(projectId);

			IList<ContentEntity> contents = DALFacade.Instance.ContentDAL.ReadContentByProject(project);
			project.Contents = contents.ToArray();

			IList<Translation> translations = DALFacade.Instance.TranslationDAL.ReadTranslationsByProject(project);
			project.Translations = translations.ToArray();

			return project;
		}

		public void FillProject(Project project)
		{
			throw new NotImplementedException();
		}

		public IList<Error> Validate(Project project)
		{
			throw new NotImplementedException();
		}


		public void UpdateProject(Project project)
		{
			//Transfer codes to iLangl Format

			DALFacade.Instance.ProjectDAL.UpdateProject(project, null);

			foreach (ContentEntity content in project.Contents)
			{
				DALFacade.Instance.ContentDAL.UpdateContent(content, null);
			}

			foreach (Translation translation in project.Translations)
			{
				if (translation.Responsible != null)
				{
					CompanyManager.Instance.UpdateCompany((Company)translation.Responsible.Company);
					ContactManager.Instance.UpdateContact(translation.Responsible);
				}

				DALFacade.Instance.TranslationDAL.UpdateTranslation(translation, null);
			}
		}

		public void AddSubscriber(Project project, PluginLicense license, bool isNeedtoSync)
		{
			//We not add subscribers for plugin where push service is not available
			if (!license.Plugin.IsPushingEnabled)
			{
				return;
			}

			SynchronizationManager.Instance.AddSubscriber(eEntityType.Project, project.Id, license, isNeedtoSync);

			foreach (Translation translation in project.Translations)
			{
				SynchronizationManager.Instance.AddSubscriber(eEntityType.Translation, translation.Id, license, isNeedtoSync);
			}

			foreach (ContentEntity content in project.Contents)
			{
				SynchronizationManager.Instance.AddSubscriber(eEntityType.Content, content.Id, license, isNeedtoSync);
			}
		}

		public void RemoveSubscriber(Project project, String subscriberId)
		{
			SynchronizationManager.Instance.RemoveSubscriber(eEntityType.Project, project.Id, subscriberId);

			foreach (Translation translation in project.Translations)
			{
				SynchronizationManager.Instance.RemoveSubscriber(eEntityType.Translation, translation.Id, subscriberId);
			}

			foreach (ContentEntity content in project.Contents)
			{
				SynchronizationManager.Instance.RemoveSubscriber(eEntityType.Content, content.Id, subscriberId);
			}
		}
	}
}
